package com.gitee.simons.common.tree;

import com.gitee.simons.common.utils.GsonUtil;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 树形构建工具
 * @author JSM
 */
public class StrTreeBuilder {

    public <T extends StrTreeModel> List<StrNode<T>> buildListToTree(List<StrNode<T>> dirs) {
        List<StrNode<T>> roots = findRoots(dirs);
        for (StrNode<T> root : roots) {
            findChildren(root, dirs);
        }
        return roots;
    }

    public <T extends StrTreeModel> List<StrNode<T>> findRoots(List<StrNode<T>> allNodes) {
        List<StrNode<T>> results = new ArrayList<StrNode<T>>();
        for (StrNode<T> node : allNodes) {
            boolean isRoot = true;
            for (StrNode<T> comparedOne : allNodes) {
                if (node!= null && comparedOne!=null&& node.getEntity().getParentId().equals( comparedOne.getEntity().getId() )) {
                    isRoot = false;
                    break;
                }
            }
            if (isRoot) {
                results.add(node);
            }
        }
        return results;
    }

    public <T extends StrTreeModel> List<StrNode<T>> findChildren(StrNode<T> root, List<StrNode<T>> allNodes) {
        List<StrNode<T>> children = new ArrayList<StrNode<T>>();

        for (StrNode<T> comparedOne : allNodes) {
            if (comparedOne.getEntity().getParentId().equals( root.getEntity().getId())) {
                children.add(comparedOne);
            }
        }
        for (StrNode<T> child : children) {
            List<StrNode<T>> tmpChildren = findChildren(child, allNodes);
            child.setChildren(tmpChildren);
        }
        root.setChildren(children);
        return children;
    }

    public <T extends StrTreeModel> List<Map<String,Object>> node2Tree(List<StrNode<T>> allNodes){
        List<Map<String,Object>> result = new ArrayList<Map<String, Object>>();

        for (StrNode<T> node : allNodes) {
            Map<String,Object> item = this.object2Map(node);
            if(node.getChildren() != null){
                item.put("children", this.node2Tree(node.getChildren()));
            }
            result.add(item);
        }

        return result;
    }

    public <T extends StrTreeModel> Map<String,Object> object2Map(StrNode<T> node){
        Map<String,Object> result = GsonUtil.gson.fromJson(GsonUtil.gson.toJson(node.getEntity()), Map.class);
        result.put("label", result.get("name"));
        result.put("key", result.get("id"));
        return result;
    }

    private static final StrTreeBuilder TD = new StrTreeBuilder();

    public static <T extends StrTreeModel> List<Map<String,Object>> model2Tree(List<T> modelList){
        List<StrNode<T>> nodelList = new ArrayList<StrNode<T>>();

        for(T item : modelList){
            StrNode<T> node = new StrNode<T>();
            node.setEntity(item);
            nodelList.add(node);
        }
        List<StrNode<T>> roots = TD.buildListToTree(nodelList);
        return TD.node2Tree(roots);
    }

}